package al.work.dataserialize.buildserial;

/**
 * @author JiuZh
 */
public class bs_helper {
    public static class bs_in_helper implements i_stream_helper.i_in_stream {

        public bs_in_helper(byte[] _data, int _index, int _length) {
            data_ = _data;
            offset_ = _index;
            length_ = offset_ + _length;
        }

        /**
         * 获取一个int8类型的数据
         * @return null 为 失败
         */
        public Byte read_int_8() {
            if (left() < 1) {
                return null;
            }
            Byte result = data_[offset_];
            shift(1);
            return result;
        }

        /**
         * 获取一个uint8类型的数据
         *
         * @return
         */
        public Short read_uint_8() {
            if (left() < 1) {
                return null;
            }
            short result = (short) (data_[offset_] & 0xff);
            shift(1);
            return result;
        }

        /**
         * 获取一个int16类型的数据
         *
         * @return
         */
        public Short read_int_16() {
            if (left() < 2) {
                return null;
            }
            int ch1 = data_[offset_];
            int ch2 = data_[offset_ + 1] & 0xff;
            Short result = (short)((ch1 << 8) + (ch2 << 0));
            shift(2);
            return result;
        }

        /**
         * 获取一个uint16类型的数据
         *
         * @return
         */
        public Integer read_uint_16() {
            if (left() < 2) {
                return null;
            }
            int ch1 = data_[offset_] & 0xff;
            int ch2 = data_[offset_ + 1] & 0xff;
            Integer result = ((ch1 << 8) + (ch2 << 0));
            shift(2);
            return result;
        }

        /**
         * 获取一个int32类型的数据
         *
         * @return
         */
        public Integer read_int_32() {
            if (left() < 4) {
                return null;
            }
            int ch1 = data_[offset_];
            int ch2 = data_[offset_ + 1] & 0xff;
            int ch3 = data_[offset_ + 2] & 0xff;
            int ch4 = data_[offset_ + 3] & 0xff;
            Integer result = ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
            shift(4);
            return result;
        }

        /**
         * 获取一个uint32类型的数据
         *
         * @return
         */
        public Long read_uint_32() {
            if (left() < 4) {
                return null;
            }
            long ch1 = data_[offset_] & 0xff;
            long ch2 = data_[offset_ + 1] & 0xff;
            long ch3 = data_[offset_ + 2] & 0xff;
            long ch4 = data_[offset_ + 3] & 0xff;
            Long result = ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
            shift(4);
            return result;
        }

        /**
         * 获取一个int64类型的数据
         *
         * @return
         */
        public Long read_int_64() {
            if (left() < 8) {
                return null;
            }
            Long result = (((long)data_[offset_] << 56) +
                    ((long)(data_[offset_ + 1] & 0xff) << 48) +
                    ((long)(data_[offset_ + 2] & 0xff) << 40) +
                    ((long)(data_[offset_ + 3] & 0xff) << 32) +
                    ((long)(data_[offset_ + 4] & 0xff) << 24) +
                    ((data_[offset_ + 5] & 0xff) << 16) +
                    ((data_[offset_ + 6] & 0xff) <<  8) +
                    ((data_[offset_ + 7] & 0xff) <<  0));
            shift(8);
            return result;
        }
        /**
         * 获取一个float类型的数据
         *
         * @return
         */
        public Float read_float() {
            Integer vl = read_int_32();
            if (null == vl) {
                return null;
            }
            return Float.intBitsToFloat(vl.intValue());
        }
        /**
         * 获取一个double类型的数据
         *
         * @return
         */
        public Double read_double() {
            Long vl = read_int_64();
            if (null == vl) {
                return null;
            }
            return Double.longBitsToDouble(vl.longValue());
        }

        /**
         * 获取一段字节数组
         *
         * @param data
         * @return
         */
        public boolean read_bytes(byte[] data) {
            return read_bytes(data, 0, data.length);
        }

        /**
         * 获取一段字节数组，从index开始写入
         *
         * @param data
         * @param index
         * @return
         */
        public boolean read_bytes(byte[] data, int index) {
            return read_bytes(data, index, data.length - index);
        }

        /**
         * 获取一段字节数组，从index开始写入，并写入count个
         *
         * @param data
         * @param index
         * @param count
         * @return
         */
        public boolean read_bytes(byte[] data, int index, int count) {
            if (index < 0 || count < 0 || index + count > data.length) {
                return false;
            }
            if (left() < count) {
                return false;
            }
            System.arraycopy(data_, offset_, data, index, count);
            shift(count);
            return true;
        }
        /**
         * 生成一个子序列化输入流对象，需要count长度
         * @param count
         * @return
         */
        public i_stream_helper.i_in_stream child_stream(int count) {
            if (left() < count) {
                return null;
            }
            i_stream_helper.i_in_stream result = new bs_in_helper(data_, offset_, (int)count);
            shift((int) count);
            return result;
        }

        private int left() {
            return length_ - offset_;
        }
        private void shift(int _len) {
            offset_ += _len;
        }

        private byte[] data_ = null;
        private int offset_ = 0;
        private int length_ = 0;
    }

    public static class bs_out_helper implements i_stream_helper.i_out_stream {

        public bs_out_helper(byte[] _data, int _index, int _length) {
            data_ = _data;
            offset_ = _index;
            length_ = offset_ + _length;
        }

        /**
         * 写入一个int8类型的数据
         *
         * @param data
         * @return
         */
        public boolean write_int_8(byte data) {
            if (left() < 1) {
                return false;
            }
            data_[offset_] = data;
            shift(1);
            return true;
        }

        /**
         * 写入一个uint8类型的数据
         *
         * @param data
         * @return
         */
        public boolean write_uint_8(short data) {
            if (left() < 1) {
                return false;
            }
            data_[offset_] = (byte)(data & 0xff);
            shift(1);
            return true;
        }

        /**
         * 写入一个int16类型的数据
         *
         * @param data
         * @return
         */
        public boolean write_int_16(short data) {
            if (left() < 2) {
                return false;
            }
            data_[offset_] = (byte) (data >> 8 & 0xFF);
            data_[offset_ + 1] = (byte) (data >> 0 & 0xFF);
            shift(2);
            return true;
        }

        /**
         * 写入一个uint16类型的数据
         *
         * @param data
         * @return
         */
        public boolean write_uint_16(int data) {
            if (left() < 2) {
                return false;
            }
            data_[offset_] = (byte) (data >> 8 & 0xFF);
            data_[offset_ + 1] = (byte) (data >> 0 & 0xFF);
            shift(2);
            return true;
        }

        /**
         * 写入一个int32类型的数据
         *
         * @param data
         * @return
         */
        public boolean write_int_32(int data) {
            if (left() < 4) {
                return false;
            }
            data_[offset_] = (byte) (data >> 24 & 0xFF);
            data_[offset_ + 1] = (byte) (data >> 16 & 0xFF);
            data_[offset_ + 2] = (byte) (data >> 8 & 0xFF);
            data_[offset_ + 3] = (byte) (data >> 0 & 0xFF);
            shift(4);
            return true;
        }

        /**
         * 写入一个uint32类型的数据
         *
         * @param data
         * @return
         */
        public boolean write_uint_32(long data) {
            if (left() < 4) {
                return false;
            }
            data_[offset_] = (byte) (data >> 24 & 0xFF);
            data_[offset_ + 1] = (byte) (data >> 16 & 0xFF);
            data_[offset_ + 2] = (byte) (data >> 8 & 0xFF);
            data_[offset_ + 3] = (byte) (data >> 0 & 0xFF);
            shift(4);
            return true;
        }

        /**
         * 写入一个int64类型的数据
         *
         * @param data
         * @return
         */
        public boolean write_int_64(long data) {
            if (left() < 8) {
                return false;
            }
            data_[offset_] = (byte) (data >> 56 & 0xFF);
            data_[offset_ + 1] = (byte) (data >> 48 & 0xFF);
            data_[offset_ + 2] = (byte) (data >> 40 & 0xFF);
            data_[offset_ + 3] = (byte) (data >> 32 & 0xFF);
            data_[offset_ + 4] = (byte) (data >> 24 & 0xFF);
            data_[offset_ + 5] = (byte) (data >> 16 & 0xFF);
            data_[offset_ + 6] = (byte) (data >> 8 & 0xFF);
            data_[offset_ + 7] = (byte) (data >> 0 & 0xFF);
            shift(8);
            return true;
        }

        /**
         * 写入一个float类型的数据
         *
         * @param data
         * @return
         */
        public boolean write_float(float data) {
            return write_int_32(Float.floatToIntBits(data));
        }

        /**
         * 写入一个double类型的数据
         *
         * @param data
         * @return
         */
        public boolean write_double(double data) {
            return write_int_64(Double.doubleToLongBits(data));

        }

        /**
         * 写入一段字节数组
         *
         * @param data
         * @return
         */
        public boolean write_bytes(byte[] data) {
            return write_bytes(data, 0, data.length);
        }

        /**
         * 写入一段字节数组,从index开始的所有
         *
         * @param data
         * @param index
         * @return
         */
        public boolean write_bytes(byte[] data, int index) {
            return write_bytes(data, index, data.length - index);
        }

        /**
         * 写入一段字节数组，从index开始的count个
         *
         * @param data
         * @param index
         * @param count
         * @return
         */
        public boolean write_bytes(byte[] data, int index, int count) {
            if (index < 0 || count < 0 || index + count > data.length) {
                return false;
            }
            if (left() < count) {
                return false;
            }
            System.arraycopy(data, index, data_, offset_, count);
            shift(count);
            return true;
        }

        private int left() {
            return length_ - offset_;
        }
        private void shift(int _len) {
            offset_ += _len;
        }

        private byte[] data_ = null;
        private int offset_ = 0;
        private int length_ = 0;
    }
}
